from datetime import datetime

from bson import ObjectId
from pydantic import Field, BaseModel


class _ObjectId(ObjectId):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v, i):
        if not ObjectId.is_valid(v):
            raise ValueError("Invalid objectid")
        return ObjectId(v)

    @classmethod
    def __get_pydantic_json_schema__(cls, field_schema):
        field_schema.update(type="string")


class MongoBaseItem(BaseModel):
    id: _ObjectId = Field(default_factory=_ObjectId, alias="_id")
    created_at: datetime = Field(default_factory=datetime.now)
    updated_at: datetime = Field(default_factory=datetime.now)

    class Config:
        populate_by_name = True
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}

    def dict(self, **kwargs):
        by_alias = kwargs.pop('by_alias', True)
        return super().dict(by_alias=by_alias, **kwargs)

    def dict_exclude_id(self, **kwargs):
        exclude = kwargs.pop('exclude', None)
        return self.dict(exclude=exclude, **kwargs)
